﻿///////////////////////////////////////////////////////
//
// XDesigner.ORM 
//
// autohr : yuans
//
// date: 2011-2-23
//
// email  : yyf9989@hotmail.com
// 
//
///////////////////////////////////////////////////////

using System;
using System.Text;
using System.Data;

namespace XDesigner.ORM
{

    /// <summary>
    /// 用于存储数据库命令信息的对象
    /// </summary>
    /// <remarks>编制 袁永福</remarks>
    [Serializable()]
    public class ORMDBCommand : ICloneable , IDisposable
    {
        public static void AppendParameterSQL(
            StringBuilder mySQL,
            string fieldName,
            object Value,
            ParameterStyle parameterStyle)
        {
            AppendParameterSQL(mySQL, fieldName, Value, parameterStyle, null);
        }

        public static string BuildConditionSQL(
            QueryConditionList conditions ,
            ParameterStyle parameterStyle ,
            ORMDBCommand cmd )
        {
            if (conditions == null || conditions.Count == 0)
            {
                return null;
            }
            StringBuilder mySQL = new StringBuilder();
            foreach (QueryCondition condition in conditions)
            {
                if (Util.HasContent(condition.FieldName) == false )
                {
                    continue;
                }
                if (mySQL.Length > 0)
                {
                    mySQL.Append(" " + conditions.ContactOperator + " ");
                }
                if (condition.Value != null && DBNull.Value.Equals(condition.Value) == false)
                {
                    string method = condition.Method;
                    if (method != null)
                    {
                        method = method.Trim().ToLower();
                        if (method == "in" || method == "not in")
                        {
                            mySQL.Append(condition.FieldName + " " + condition.Method + " (" + condition.Value + ") ");
                            continue;
                        }
                        else if (method == "like")
                        {
                            mySQL.Append(condition.FieldName + " " + condition.Method + " '" + condition.Value + "' ");
                            continue;
                        }
                        else if (method == "is")
                        {
                            mySQL.Append(condition.FieldName + " " + condition.Method + " " + condition.Value + " ");
                            continue;
                        }
                        mySQL.Append(condition.FieldName + " " + condition.Method + " ");
                        AppendParameterSQL(
                            mySQL,
                            condition.Name,
                            condition.Value,
                            parameterStyle,
                            cmd);
                    }
                    else
                    {
                        mySQL.Append(condition.FieldName);
                    }
                }
            }//foreach
            return mySQL.ToString();
        }

        public static void AppendParameterSQL(
            StringBuilder mySQL,
            string fieldName,
            object Value,
            ParameterStyle parameterStyle,
            ORMDBCommand command)
        {
            if (Value == null)
            {
                Value = DBNull.Value;
            }
            if (Value is string)
            {
                string str = (string)Value;
                if (str == null || str.Length == 0)
                {
                    Value = DBNull.Value;
                }
            }
            switch (parameterStyle)
            {
                case ParameterStyle.Anonymous:
                    mySQL.Append(" ? ");
                    if (command != null)
                    {
                        ORMDBParameter p = new ORMDBParameter();
                        p.Value = Value;
                        command.Parameters.Add(p);
                    }
                    break;
                case ParameterStyle.Default:
                    mySQL.Append(" ? ");
                    if (command != null)
                    {
                        ORMDBParameter p = new ORMDBParameter();
                        p.Value = Value;
                        command.Parameters.Add(p);
                    }
                    break;
                case ParameterStyle.Macro:
                    if (Value == null || DBNull.Value.Equals(Value))
                    {
                        mySQL.Append(" null ");
                    }
                    else if (Value is string)
                    {
                        string str = (string)Value;
                        if (str.Length == 0)
                        {
                            mySQL.Append(" null ");
                        }
                        else
                        {
                            if (str.IndexOf("'") >= 0)
                            {
                                str = str.Replace("'", "''");
                            }
                            mySQL.Append("'" + str + "'");
                        }
                    }
                    else if (Value is byte[])
                    {
                        byte[] bs = (byte[])Value;
                        if (bs.Length == 0)
                        {
                            mySQL.Append(" null ");
                        }
                        else
                        {
                            char[] hexs = "0123456789ABCDEF".ToCharArray();
                            mySQL.Append("0x");
                            for (int iCount = 0; iCount < bs.Length; iCount++)
                            {
                                byte b = bs[iCount];
                                mySQL.Append(hexs[b >> 4]);
                                mySQL.Append(hexs[b & 15]);
                            }
                        }
                    }
                    else if (Value is DateTime)
                    {
                        mySQL.Append("'" + Value.ToString() + "'");
                    }
                    else
                    {
                        mySQL.Append(Value.ToString());
                    }
                    break;
                case ParameterStyle.OracleStyle:
                    mySQL.Append(":" + fieldName);
                    if (command != null)
                    {
                        ORMDBParameter p = new ORMDBParameter();
                        p.ParameterName = fieldName;
                        p.Value = Value;
                        command.Parameters.Add(p);
                    }
                    break;
                case ParameterStyle.SQLServerStyle:
                    mySQL.Append("@" + fieldName);
                    if (command != null)
                    {
                        ORMDBParameter p = new ORMDBParameter();
                        p.ParameterName = fieldName;
                        p.Value = Value;
                        command.Parameters.Add(p);
                    }
                    break;
                default:
                    mySQL.Append("@" + fieldName);
                    if (command != null)
                    {
                        ORMDBParameter p = new ORMDBParameter();
                        p.ParameterName = fieldName;
                        p.Value = Value;
                        command.Parameters.Add(p);
                    }
                    break;
            }//switch
        }

        /// <summary>
        /// 初始化对象
        /// </summary>
        public ORMDBCommand()
        {
        }

        /// <summary>
        /// 初始化对象
        /// </summary>
        public ORMDBCommand( ORMEngine engine )
        {
            _Engine = engine;
        }

        /// <summary>
        /// 初始化对象
        /// </summary>
        /// <param name="commandText">命令文本</param>
        public ORMDBCommand(string commandText)
        {
            strCommandText = commandText;
        }

        private string strCommandText = null;
        /// <summary>
        /// 命令文本
        /// </summary>
        public string CommandText
        {
            get
            {
                return strCommandText;
            }
            set
            {
                strCommandText = value;
            }
        }

        private int intCommandTimeout = 30;
        /// <summary>
        /// 超时时间，单位秒，默认30秒。
        /// </summary>
        [System.ComponentModel.DefaultValue(30)]
        public int CommandTimeout
        {
            get
            {
                return intCommandTimeout;
            }
            set
            {
                intCommandTimeout = value;
            }
        }

        private ORMDBParameterList myParameters = new ORMDBParameterList();
        /// <summary>
        /// 参数列表
        /// </summary>
        public ORMDBParameterList Parameters
        {
            get
            {
                return myParameters;
            }
            set
            {
                myParameters = value;
            }
        }

        public ORMDBParameter AddParameter(string name, object Value)
        {
            ORMDBParameter p = new ORMDBParameter(name, Value);
            this.Parameters.Add(p);
            return p;
        }



        public void ClearParameter()
        {
            this.Parameters.Clear();
        }

        private ORMEngine _Engine = null;

        public ORMEngine Engine
        {
            get { return _Engine; }
            set { _Engine = value; }
        }

        private bool _UserCancel = false;
        /// <summary>
        /// User cancel operation
        /// </summary>
        [System.ComponentModel.Browsable( false )]
        public bool UserCancel
        {
            get
            {
                return _UserCancel; 
            }
        }

        private IDbCommand _InnerDBCommand = null;
        public void CheckInnerDBCommand()
        {
            if (_InnerDBCommand == null)
            {
                if (_Engine != null)
                {
                    _InnerDBCommand = _Engine.CreateDBCommand();
                    if (_InnerDBCommand == null)
                    {
                        _UserCancel = true;
                        return;
                    }
                }
            }
            if (_InnerDBCommand == null)
            {
                throw new InvalidOperationException("Can not open database");
            }
            else
            {
                _InnerDBCommand.CommandText = this.CommandText;
                _InnerDBCommand.CommandTimeout = this.CommandTimeout;
                _InnerDBCommand.Parameters.Clear();
                foreach (ORMDBParameter p in this.Parameters)
                {
                    IDbDataParameter p2 = _InnerDBCommand.CreateParameter();
                    p2.ParameterName = p.ParameterName;
                    if (p.Value == null)
                    {
                        p2.Value = DBNull.Value;
                    }
                    else if (p.Value is string
                    && string.IsNullOrEmpty((string)p.Value))
                    {
                        p2.Value = DBNull.Value;
                    }
                    else
                    {
                        p2.Value = p.Value;
                    }
                    _InnerDBCommand.Parameters.Add(p2);
                }
            }
        }
         
        public int ExecuteNonQuery()
        {
            CheckInnerDBCommand();
            if (this.UserCancel)
            {
                return 0;
            }
            else
            {
                int result = _InnerDBCommand.ExecuteNonQuery();
                ORMPerformanceCounter.Increment("ExecuteNonQuery");
                ORMPerformanceCounter.Increment( ORMPerformanceCounter.Name_ExecuteCommand );
                return result;
            }
        }

        public object ExecuteScalar()
        {
            CheckInnerDBCommand();
            if (this.UserCancel)
            {
                return DBNull.Value;
            }
            else
            {
                object obj = _InnerDBCommand.ExecuteScalar();
                ORMPerformanceCounter.Increment("ExecuteScalar");
                ORMPerformanceCounter.Increment(ORMPerformanceCounter.Name_ExecuteCommand);
                return obj;
            }
        }

        public IDataReader ExecuteReader()
        {
            CheckInnerDBCommand();
            if (this.UserCancel)
            {
                return null;
            }
            else
            {
                IDataReader reader = _InnerDBCommand.ExecuteReader();
                ORMPerformanceCounter.Increment("ExecuteReader");
                ORMPerformanceCounter.Increment(ORMPerformanceCounter.Name_ExecuteCommand);
                return reader;
            }
        }

        public IDataReader ExecuteReader(CommandBehavior behavior)
        {
            CheckInnerDBCommand();
            if (this.UserCancel)
            {
                return null;
            }
            else
            {
                IDataReader reader = _InnerDBCommand.ExecuteReader(behavior);
                ORMPerformanceCounter.Increment("ExecuteReader");
                ORMPerformanceCounter.Increment(ORMPerformanceCounter.Name_ExecuteCommand);
                return reader;
            }
        }

        /// <summary>
        /// 根据对象数据创建一个实际使用的数据库命令对象
        /// </summary>
        /// <param name="conn">数据库连接对象</param>
        /// <returns>创建的的数据库命令对象</returns>
        public IDbCommand CreateCommand(IDbConnection conn)
        {
            System.Data.IDbCommand cmd = conn.CreateCommand();
            cmd.CommandText = this.CommandText;
            cmd.CommandTimeout = this.CommandTimeout;
            foreach (ORMDBParameter p in myParameters)
            {
                IDbDataParameter p2 = cmd.CreateParameter();
                if (p.ParameterName != null)
                {
                    p2.ParameterName = p.ParameterName;
                }
                if (p.Value == null)
                {
                    p2.Value = DBNull.Value;
                }
                else if (p.Value is string
                    && string.IsNullOrEmpty((string)p.Value))
                {
                    p2.Value = DBNull.Value;
                }
                else
                {
                    p2.Value = p.Value;
                }
                p2.SourceColumn = p.SourceColumn;
                cmd.Parameters.Add(p2);
            }
            return cmd;
        }

        /// <summary>
        /// 复制对象
        /// </summary>
        /// <returns>复制品</returns>
        object System.ICloneable.Clone()
        {
            ORMDBCommand info = new ORMDBCommand();
            info.intCommandTimeout = this.intCommandTimeout;
            info._Engine = this._Engine;
            info._UserCancel = this._UserCancel;
            info.myParameters = new ORMDBParameterList();
            foreach (ORMDBParameter p in myParameters)
            {
                info.myParameters.Add(p.Clone());
            }
            info.strCommandText = this.strCommandText;

            return info;
        }

        /// <summary>
        /// 复制对象
        /// </summary>
        /// <returns>复制品</returns>
        public ORMDBCommand Clone()
        {
            return (ORMDBCommand)((System.ICloneable)this).Clone();
        }

        public void Dispose()
        {
            if (_InnerDBCommand != null)
            {
                _InnerDBCommand.Dispose();
                _InnerDBCommand = null;
            }
        }

        
        public void DebugPrint( string source )
        {
            System.Diagnostics.Debug.WriteLine(source + ":" + this.CommandText);
            foreach ( ORMDBParameter p in this.Parameters )
            {
                if (p.Value == null || DBNull.Value.Equals(p.Value))
                {
                    System.Diagnostics.Debug.WriteLine("Parameter:" + p.ParameterName + "\t=NULL");
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("Parameter:" + p.ParameterName + "\t=\"" + p.Value + "\"");
                }
            }
        }

         
    }


    /// <summary>
    /// 数据源参数对象
    /// </summary>
    [Serializable()]
    public class ORMDBParameter : System.ICloneable
    {
        /// <summary>
        /// 初始化对象
        /// </summary>
        public ORMDBParameter()
        {
        }

        /// <summary>
        /// 初始化对象
        /// </summary>
        /// <param name="name">参数名称</param>
        public ORMDBParameter(string name)
        {
            strParameterName = name;
        }

        public ORMDBParameter(string name, object value)
        {
            strParameterName = name;
            objValue = value;
        }

        private string strParameterName = null;
        /// <summary>
        /// 参数名称
        /// </summary>
        [System.ComponentModel.DefaultValue(null)]
        [System.ComponentModel.Category("Design")]
        public string ParameterName
        {
            get
            {
                return strParameterName;
            }
            set
            {
                strParameterName = value;
            }
        }
         

        private object objValue = null;
        /// <summary>
        /// 参数值
        /// </summary>
        [System.ComponentModel.Browsable(false)]
        [System.Xml.Serialization.XmlIgnore()]
        public object Value
        {
            get
            {
                return objValue;
            }
            set
            {
                objValue = value;
            }
        }

        public ORMValue Value2
        {
            get
            {
                return new ORMValue(objValue);
            }
            set
            {
                objValue = value.RawValue;
            }
        }

        private string _SourceColumn = null;

        public string SourceColumn
        {
            get { return _SourceColumn; }
            set { _SourceColumn = value; }
        }

        /// <summary>
        /// 返回表示对象的字符串
        /// </summary>
        /// <returns>字符串</returns>
        public override string ToString()
        {
            return strParameterName + "=" + objValue;
        }

        /// <summary>
        /// 复制对象
        /// </summary>
        /// <returns>复制品</returns>
        object System.ICloneable.Clone()
        {
            ORMDBParameter p = new ORMDBParameter();
            p.strParameterName = strParameterName;
            p.objValue = objValue;
            p._SourceColumn = this._SourceColumn;
            return p;
        }

        /// <summary>
        /// 复制对象
        /// </summary>
        /// <returns>复制品</returns>
        public ORMDBParameter Clone()
        {
            ORMDBParameter p = new ORMDBParameter();
            p.strParameterName = strParameterName;
            p.objValue = objValue;
            p._SourceColumn = this._SourceColumn;
            return p;
        }
    }
    /// <summary>
    /// 参数列表对象
    /// </summary>
    [Serializable()]
    [System.Diagnostics.DebuggerDisplay("ORMDBParameterList Count={ Count }")]
    [System.Diagnostics.DebuggerTypeProxy(typeof(ORMDebugView))]
    public class ORMDBParameterList : System.Collections.CollectionBase, System.ICloneable
    {
        /// <summary>
        /// 初始化对象
        /// </summary>
        public ORMDBParameterList()
        {
        }
        /// <summary>
        /// 获得指定序号处的参数对象
        /// </summary>
        /// <param name="index">序号</param>
        /// <returns>参数对象</returns>
        public ORMDBParameter this[int index]
        {
            get
            {
                return (ORMDBParameter)this.List[index];
            }
        }
        /// <summary>
        /// 获得指定名称的参数对象
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <returns>参数对象</returns>
        public ORMDBParameter this[string name]
        {
            get
            {
                foreach (ORMDBParameter p in this)
                {
                    if (string.Compare(p.ParameterName, name, true) == 0)
                        return p;
                }
                return null;
            }
        }
        /// <summary>
        /// 向列表添加新的参数对象
        /// </summary>
        /// <param name="item">参数对象</param>
        /// <returns>新对象在列表中的序号</returns>
        public int Add(ORMDBParameter item)
        {
            return this.List.Add(item);
        }

        /// <summary>
        /// Add parameter
        /// </summary>
        /// <param name="name"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public ORMDBParameter AddParameter(string name, object Value)
        {
            ORMDBParameter p = new ORMDBParameter();
            p.ParameterName = name;
            p.Value = Value;
            this.List.Add(p);
            return p;
        }

        /// <summary>
        /// 删除指定的参数对象
        /// </summary>
        /// <param name="item">参数对象</param>
        public void Remove(ORMDBParameter item)
        {
            this.List.Remove(item);
        }
        /// <summary>
        /// 删除指定名称的参数对象
        /// </summary>
        /// <param name="name">参数名称</param>
        public void Remove(string name)
        {
            ORMDBParameter p = this[name];
            if (p != null)
            {
                this.List.Remove(p);
            }
        }
          

        /// <summary>
        /// 判断是否存在指定名称的参数对象
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <returns>是否存在指定名称的参数对象</returns>
        public bool Contains(string name)
        {
            return this[name] != null;
        }
        /// <summary>
        /// 复制对象
        /// </summary>
        /// <returns>复制品</returns>
        object System.ICloneable.Clone()
        {
            ORMDBParameterList list = new ORMDBParameterList();
            foreach (ORMDBParameter p in this)
            {
                list.List.Add(p.Clone());
            }
            return list;
        }
        /// <summary>
        /// 复制对象
        /// </summary>
        /// <returns>复制品</returns>
        public ORMDBParameterList Clone()
        {
            ORMDBParameterList list = new ORMDBParameterList();
            foreach (ORMDBParameter p in this)
            {
                list.List.Add(p.Clone());
            }
            return list;
        }

        /// <summary>
        /// 返回参数对象组成的数组
        /// </summary>
        /// <returns>对象数组</returns>
        public ORMDBParameter[] ToArray()
        {
            return (ORMDBParameter[])this.InnerList.ToArray(typeof(ORMDBParameter));
        }
        /// <summary>
        /// 获得所有参数名称组成的数组
        /// </summary>
        /// <returns>名称数组</returns>
        public string[] GetNames()
        {
            string[] names = new string[this.Count];
            for (int iCount = 0; iCount < this.Count; iCount++)
            {
                names[iCount] = ((ORMDBParameter)this.List[iCount]).ParameterName;
            }
            return names;
        }

        public override string ToString()
        {
            return this.Count + " parameters";
        }
    }
     
}
